package com.aaa.controller;

import com.aaa.entity.Result;
import com.aaa.entity.Users;
import com.aaa.service.UserService;
import com.aaa.util.TokenUtil;
import com.aaa.util.ThreadLocalUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;

@Validated
@RestController
@RequestMapping("/api/users")
public class UserController {

    // 用于验证输入的手机号码格式
    private static final String PHONE_REGEX = "^1[3-9]\\d{9}$";
    // 定义允许的特殊字符
    private static final String SPECIAL_CHARS = "@#$%^&+=!*()_.,?/-_";
    // 定义密码的正则表达式，要求密码长度在 8 - 20 位之间，
    // 并且必须包含字母、数字和特殊字符
    private static final String PASSWORD_REGEX = "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[" + SPECIAL_CHARS + "])[A-Za-z\\d" + SPECIAL_CHARS + "]{8,20}$";
    // 日志记录器，用于记录操作信息和异常信息
    private static final Logger logger = LoggerFactory.getLogger(UserController.class);
    @Autowired
    private UserService userService;

    /**
     * 用户登录接口，处理用户登录请求。
     *
     * @param phoneNumber 用户输入的手机号码
     * @param password    用户输入的密码
     * @return 返回登录结果，成功则返回包含 token 的 Result 对象，失败则返回错误信息
     */
    @PostMapping("/login")
    public ResponseEntity<Result<?>> loginUser(
            @RequestParam String phoneNumber,
            @RequestParam String password) {
        logger.info("收到登录请求 - 手机号: {}", phoneNumber);
        
        // 手动验证手机号格式
        if (!phoneNumber.matches(PHONE_REGEX)) {
            logger.warn("登录失败 - 手机号: {}，原因: 手机号格式不正确", phoneNumber);
            return ResponseEntity.badRequest().body(Result.paramError("手机号格式不正确，请输入有效的11位手机号"));
        }
        
        // 验证密码格式 - 登录时可以放宽一些要求，仅验证密码非空
        if (password == null || password.isEmpty()) {
            logger.warn("登录失败 - 手机号: {}，原因: 密码不能为空", phoneNumber);
            return ResponseEntity.badRequest().body(Result.paramError("密码不能为空"));
        }
        
        // 检查手机号是否存在
        if (!userService.isPhoneNumberExists(phoneNumber)) {
            logger.warn("登录失败 - 手机号: {}，原因: 手机号不存在", phoneNumber);
            return ResponseEntity.badRequest().body(Result.paramError("手机号不存在"));
        }
        
        // 检查密码是否正确
        Users loginUser = userService.loginUser(phoneNumber, password);
        if (loginUser == null) {
            logger.warn("登录失败 - 手机号: {}，原因: 密码错误", phoneNumber);
            return ResponseEntity.badRequest().body(Result.paramError("密码错误"));
        }
        
        logger.info("用户登录成功 - 用户ID: {}", loginUser.getId());
        // 创建一个 Map 用于存储生成 token 所需的声明信息
        Map<String, Object> claims = new HashMap<>();
        // 将用户的 id 放入声明信息中
        claims.put("id", loginUser.getId());
        // 调用 TokenUtil 的 genToken 方法生成 token
        String token = TokenUtil.genToken(claims);
        // 创建包含 token、userId 和 username 的 data 映射
        Map<String, Object> data = new HashMap<>();
        data.put("token", "Bearer " + token);
        data.put("user", loginUser);
        logger.info("Token生成成功 - 用户ID: {}", loginUser.getId());
        return ResponseEntity.ok(Result.success(data));
    }

    /**
     * 根据用户 id 修改密码的接口，处理用户修改密码的请求。
     *
     * @param newPassword     用户输入的新密码
     * @param confirmPassword 用户输入的确认新密码
     * @return 返回修改密码的结果，成功则返回成功信息，失败则返回错误信息
     */
    @PutMapping("/updatePassword")
    public ResponseEntity<Result<?>> updatePassword(
            @RequestParam String newPassword,
            @RequestParam String confirmPassword) {
        
        logger.info("修改密码请求 - 开始处理");
        
        // 验证密码格式
        if (!newPassword.matches(PASSWORD_REGEX)) {
            logger.warn("修改密码失败 - 原因: 密码格式不正确");
            return ResponseEntity.badRequest().body(Result.paramError("密码格式不正确，必须包含字母、数字和特殊字符，长度8-20位"));
        }
        
        // 验证两次输入的新密码是否一致
        if (!newPassword.equals(confirmPassword)) {
            logger.warn("修改密码失败 - 原因: 两次输入的密码不一致");
            return ResponseEntity.badRequest().body(Result.paramError("两次输入的密码不一致"));
        }
        
        Map<String, Object> claims = ThreadLocalUtil.get();
        if (claims == null || !claims.containsKey("id")) {
            logger.warn("修改密码失败 - 原因: Token无效或未提供有效的认证Token");
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(Result.unauthorized("Token无效或未提供有效的认证Token"));
        }
        
        String userId = claims.get("id").toString();
        logger.info("修改密码 - 用户ID: {}", userId);
        // 更新用户密码
        if (userService.updatePassword(userId, newPassword) > 0) {
            logger.info("修改密码成功 - 用户ID: {}", userId);
            return ResponseEntity.ok(Result.success("用户密码修改成功"));
        }
        // 如果更新密码失败，设置响应状态码为 400 Bad Request
        logger.warn("修改密码失败 - 用户ID: {}", userId);
        return ResponseEntity.badRequest().body(Result.paramError("密码修改失败"));
    }
}